;
; The Bootsector Code (First 512 bytes of the floppy)
;

;
; Define Code Segment and Data Segment Rights details for inputting to GDTFill function
;
%define CS_ACCES 10011011b ; CS and DS Access Rights (Details in GDT.INC)
%define DS_ACCES 10010011b

;
;  16 Bit Addressing initially
;
[bits 16]

;
; Code begins at 0x7c00
;
[org 0x7c00]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Bios Jumps to 0xf000:0xffff
; Then it loads the first 512 bytes (BootSector) from first boot device to 0x0000:0x7c00
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jmp boot


;
; Includes
;
%include "GDT.INC"


;
; Define Stack 
;
boot:
mov ax,0x07C0 
mov ds,ax
mov es,ax
mov ax,0x8FFF 
mov ss,ax


;
; Stack begins at 0xf000 and fills from there downwards
;
mov sp,0xFFFF 


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Note:
; Linear Address = Shift Segment by 1 byte and add Offset to it
;
; Read Kernel From Floppy to Memory location es:bx (0x1000 here)
; Cylinder Head Sector and Buffer are as follows:
; 
; es:bx - buffer where to load Kernel to
; ch    - track number
; cl    - starting sector
; dh    - head number
; dl    - drive number (0 here)
; Then call interrupt 0x13 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
xor ax,ax
int 0x13

;
; Save previous registry values
;
push es 

mov ax,0x100
mov es,ax
mov bx,0

mov ah,2
mov al,40
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 0x13

;
; Now es holds stack addresss
;
pop es

;
; Fill GDT
; Refer to GDT.INC for details
;
GDTFill 0x0,0xFFFFF,CS_ACCES,1101b,gdt_cs
GDTFill 0x0,0xFFFFF,DS_ACCES,1101b,gdt_ds

;
; Store Limit of GDT beginning at location marked as gdtptr
; This has to be passed on to lgdt instruction
;
mov ax, gdtend
mov bx, gdt
sub ax,bx
mov word [gdtptr], ax

;
; Store Linear address of GDT at gdtptr after allowing space for the previous data
; Linear Address = Shift Segment by 1 byte and add Offset to it
;
xor ax,ax 
mov ax,ds 
mov bx,gdt
call LinearAdd
mov dword [gdtptr+2], ecx 

;
; Load gdt using lgdt. Disable interrupts before that
;
cli
lgdt[gdtptr]

;
; Move to protected mode. Set cr0's first bit to 1 by or'ing it
;
mov eax,cr0
or ax,1
mov cr0,eax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Once in Protected Mode,
; Except cs all are defined w.r.t DataSegment
; DataSegment Descriptor from beginning of GDT is 8 bytes
; CodeSegment Descriptor from beginning of GDT is 10 bytes
; Stack (Very important! - This is what i messed with initially:
; --------------------------------------------------------------
; Defined w.r.t Data segment
; Beginning - 0x9f000 (Fills downwards)
; Stack size is  = 0x9f000 - DataSegment Value (= 0x0) (Have to change this)
; Quite enough for some small operations and LIBC Functions
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jmp next

next:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax 

mov esp,0x80000 ; Stack begins filling at this address

;
; protected mode segmented address = cs:0x1000
; This is nothing but 0x0:0x1000 in protected mode (Have to change these)
; Which is where kernel was loaded earlier from floppy
;
jmp dword 0x8:0x1000

end:
jmp end ; Just in case it slips the earlier step !

;
; Initially fill GDT with 0's
; 
gdt:
gdt_null:
dw 0,0,0,0
gdt_cs:
dw 0,0,0,0
gdt_ds:
dw 0,0,0,0
gdtend:


;
; The following is the GDT Pointer
; This is used for passing it on to LGDT Instruction
;
gdtptr:
dw 0x0000 ; 16 bit size of GDT
dd 0 ; 32 bit linear address of GDT


;
; Filling the rest of space with NOP
; Or else boot sector might start executing invalid instructions there
; Because of Junk Data
;
times 510-($-$$) db 144
;
; The signature of boot sector
;
dw 0xaa55 


